Skip to content

Feat/add pact cli#211

Closed
YOU54F wants to merge 7 commits intopact-foundation:masterfrom
YOU54F:feat/add-pact-cli
Closed

Feat/add pact cli#211
YOU54F wants to merge 7 commits intopact-foundation:masterfrom
YOU54F:feat/add-pact-cli

Conversation

@YOU54F
Copy link
Member

@YOU54F YOU54F commented Oct 23, 2025

This introduces the following breaking changes, with ways to preserve existing behaviour.

TL;DR - All pact rust functionality is now is a single binary pact. All commands will route to this binary, unless PACT_CLI_LEGACY env var is set, in which case, existing behaviour is preserved.

all available functionality available exposed when PACT_CLI_LEGACY is set, will be removed in a major version bump

changes

./pact/bin/
├── pact (single binary with all pact rust functionality)
├── pact-broker (legacy) - use `pact broker`
├── pactflow (legacy) - use `pact pactflow`
├── pact-message (legacy) - use `pact mock` (consumer) / `pact verifier` (provider)
├── pact-mock-service (legacy) - use `pact mock`
├── pact-provider-verifier (legacy) - use `pact verifier`
└── pact-stub-service (legacy) - use `pact stub`
  • (BREAKING): removal of pact wrapper script
  • introduction of pact cli with subcommands
    • (BREAKING) pact_mock_server_cli -> pact mock
    • (BREAKING) pact_verifier_cli -> pact verifier
    • (BREAKING) pact-plugin-cli -> pact plugin
    • (BREAKING) pact-stub-service -> pact stub
  • default routing of all legacy commands to pact <subcommand> equivalent
    • (PARTIAL BREAKING) ruby -> rust command line arguments are not identical, with exception to the pact-broker-cli
      • users can opt in to existing behaviour by setting PACT_CLI_LEGACY= to any value

This will be published under a minor release.

Current consumers

  • homebrew
    • will get latest release by default
      • provide warning on install, to advise users to opt-in to legacy commands with PACT_CLI_LEGACY or be advised to try and make it work
  • pact-js-cli
    • work required to map verifier/mock/broker/stub cli to js api
      • quickest staged roll-out is
        • to set PACT_CLI_LEGACY=1 in api
        • allow mapping to old / new bin stubs via PACT_CLI_LEGACY
  • pact-python-cli
    • is there a api surface still exposed?

Apply this approach to

Thoughts on approach?

@YOU54F YOU54F requested review from JP-Ellis and mefellows October 23, 2025 00:45
@YOU54F YOU54F marked this pull request as draft October 23, 2025 00:46
@JP-Ellis
Copy link
Contributor

Nice! I love the new subcommand names! 🚀 🥳

I wouldn't worry too much about breaking changes for Pact Python. The workflow would be:

  1. If you're using pact-python[compat-v2], it will install the old v1 CLIs to preserve backwards compatibility.
  2. If you're using pact-python, the CLIs aren't installed anyway, and you can install pact-python-cli with either v1 for compatibility, or v2 to get the new ones.

Basically, there's no big risk in upgrading, because Python's version management will allow people to downgrade.

@JP-Ellis
Copy link
Contributor

Quick question though:

Why add the PACT_CLI_LEGACY environment variable (and associated logic around that)?

If people want to use the legacy CLI, could we not just direct them to download the old CLIs?

The main benefit I can see with having the env-var toggle would be to support running both old and new CLIs... but is that really important?

@YOU54F
Copy link
Member Author

YOU54F commented Oct 24, 2025

the standalone package recently added all the rust tools to allow people to switch over.

they were introduced as new commands, so people needed to opt in to use them, without an easy way to switch between ( they dont have the same command names or args )

if we introduce a breaking change in this packaging, it means peoples workflows will automatically migrate over to use the new binaries.

with any luck, no-one is using the old ruby tools with exception to the pact broker client.

if they are, only pact-broker-cli has been designed with a one to one mapping of args, but there may be times when this isn’t the case, and definitely isn’t the case for the other ruby -> rust crates.

i actually think an easier way to roll out a change where we use legacy clis and it is opt in to use new ones via env var, avoid breaking peoples flows. any tooling can update over time, it will air out argument incompatibility and we can add shims in rust tooling ( verbose flag in ruby is available in rust pact broker cli, but hidden and will map to log-level info )

the same approach could be taken for a no action upgrade from ruby to rust binaries, with shims removed at a later date

once we sort packaging out for the pact consolidated rust cli ( homebrew / docker / script / action ), we could flip the env vars to be opt out in pact standalone.

alternatively, we remove all rust tools from bundle, create a new rust based distribution that similar to the suggestion of extensions for downloading/using pactflow-ai, it can download the legacy standalone if a legacy command is used.

i approached the extension angle like gh in the first take on the cli and had an approach to download the ruby standalone bundle ( it was actually to run a standalone broker, but the principle is the same )

cli exts https://github.com/YOU54F/pact-cli/blob/archive/main/src/cli/cli_extension.rs

downloading traveling ruby package on users machine

https://github.com/YOU54F/pact-cli/blob/archive/main/src/cli/pact_broker_standalone.rs

i have a not yet public repo for a rust based traveling-ruby package that embeds the entire standalone in the rust binary, and unarchives prior to execution.

embedding isnt preferable due to size, so we can download on the fly, following example from convo in pactflow ai pr

pact extensions install pact-legacy
pact broker-legacy publish
pact stub-legacy

@YOU54F
Copy link
Member Author

YOU54F commented Oct 24, 2025

Nice! I love the new subcommand names! 🚀 🥳

I wouldn't worry too much about breaking changes for Pact Python. The workflow would be:

  1. If you're using pact-python[compat-v2], it will install the old v1 CLIs to preserve backwards compatibility.
  2. If you're using pact-python, the CLIs aren't installed anyway, and you can install pact-python-cli with either v1 for compatibility, or v2 to get the new ones.

Basically, there's no big risk in upgrading, because Python's version management will allow people to downgrade.

thanks dude, appreciate the info, and how the workflow would look like

ahh okay so they get one or the other either automatically with v2 compat for main package or manually via cli package, could you install both cli packages together by doing install twice once with compat flag?

@YOU54F
Copy link
Member Author

YOU54F commented Oct 24, 2025

The main benefit I can see with having the env-var toggle would be to support running both old and new CLIs... but is that really important?

i do like this proposition, it makes switch between and testing a migration easier for me, and in something like the pactflow actions, i was planning on following same approach to allow the existing action to be used in compat mode.

basically the workflow there is use rust binary via its install script and bypass the existing docker cli altogether, unless the legacy env var is set.

maybe i am bleeding my testing/migration/maintainer brain into userspace.

i am just worried about breaking peoples existing workflows and trying to find the most seamless path to get people used to the new rust core.

if we just remove rust tools from here completely, that also works for me and reduces complexity/duplication

ps i have some ruby and rust side by side examples of the mock, verifier and stub in order to document the migration path for users :) they are in the pact-cli repo under examples https://github.com/YOU54F/pact-cli/tree/main/examples

@YOU54F
Copy link
Member Author

YOU54F commented Oct 25, 2025

Cheers for the inspiration.

KISS in action.

Much simplified approach in pact-foundation/pact-cli#8 which will remove a-lot of complexity and cognitive load, which was the aim of this whole exercise anyway!

@YOU54F YOU54F closed this Oct 25, 2025
@mefellows
Copy link
Member

I saw these messages and had it on my radar to review this week after the hackathon.

Not gonna lie, this new PR is definitely in the right direction!

@JP-Ellis
Copy link
Contributor

ahh okay so they get one or the other either automatically with v2 compat for main package or manually via cli package, could you install both cli packages together by doing install twice once with compat flag?

Short answer: no. Python does not typically allow you to install multiple versions of the same package within the same environment. If you really had to, you would need to do some weird shenanigans, or have a separate venv.

Love the new PR 🚀

@YOU54F YOU54F deleted the feat/add-pact-cli branch November 8, 2025 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants